package info.u250.c2d.box2deditor.ui.controls;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Pool;
import info.u250.c2d.box2deditor.adapter.PolygonFixtureDefModel;
import info.u250.c2d.box2deditor.gdx.support.Geometry;
import info.u250.c2d.box2deditor.ui.Binder;

import javax.swing.*;
import javax.swing.GroupLayout.ParallelGroup;
import javax.swing.GroupLayout.SequentialGroup;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

/**
 * This is not good for eat
 * {@link PolygonFixtureDefModel#polygon} is for editor plus
 */
public class PolygonFixtureDefPropertiesPanel extends FixtureDefPropertiesPanel implements ActionListener {
    private List<Vector2Panel> pointPanels = new ArrayList<Vector2Panel>();

    public PolygonFixtureDefPropertiesPanel() {
        GridBagLayout gridBagLayout = (GridBagLayout) getPanel().getLayout();
        gridBagLayout.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
        gridBagLayout.columnWeights = new double[]{0.0, 1.0};

        JSeparator separator = new JSeparator();
        GridBagConstraints gbc_separator = new GridBagConstraints();
        gbc_separator.fill = GridBagConstraints.HORIZONTAL;
        gbc_separator.insets = new Insets(10, 10, 5, 10);
        gbc_separator.gridx = 0;
        gbc_separator.gridy = 11;
        gbc_separator.gridwidth = 2;
        getPanel().add(separator, gbc_separator);

        JLabel lblVertices = new JLabel("vertices:");
        GridBagConstraints gbc_lblVertices = new GridBagConstraints();
        gbc_lblVertices.insets = new Insets(0, 0, 5, 5);
        gbc_lblVertices.gridx = 0;
        gbc_lblVertices.gridy = 12;
        getPanel().add(lblVertices, gbc_lblVertices);

        JLabel lblPolygonShape = new JLabel("Polygon Shape:");
        lblPolygonShape.setForeground(Color.BLUE);
        GridBagConstraints gbc_lblPolygonShape = new GridBagConstraints();
        gbc_lblPolygonShape.anchor = GridBagConstraints.WEST;
        gbc_lblPolygonShape.insets = new Insets(0, 0, 5, 5);
        gbc_lblPolygonShape.gridx = 1;
        gbc_lblPolygonShape.gridy = 12;
        getPanel().add(lblPolygonShape, gbc_lblPolygonShape);

        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        scrollPane.setPreferredSize(new Dimension(100, 150));
        GridBagConstraints gbc_scrollPane = new GridBagConstraints();
        gbc_scrollPane.insets = new Insets(0, 0, 5, 5);
        gbc_scrollPane.fill = GridBagConstraints.BOTH;
        gbc_scrollPane.gridx = 0;
        gbc_scrollPane.gridy = 13;
        gbc_scrollPane.gridwidth = 2;
        getPanel().add(scrollPane, gbc_scrollPane);

        polygonPanel = new JPanel();
        GroupLayout layout = new GroupLayout(this.polygonPanel);
        this.polygonPanel.setLayout(layout);
        // set all the flags
        layout.setAutoCreateContainerGaps(true);
        layout.setAutoCreateGaps(false);
        scrollPane.setViewportView(polygonPanel);

    }

    private static final long serialVersionUID = 1357591566550629249L;
    private JPanel polygonPanel;

    @Override
    public Class<PolygonFixtureDefModel> getType() {
        return PolygonFixtureDefModel.class;
    }

    Pool<Vector2Panel> vector2PanelPool = new Pool<Vector2Panel>() {
        @Override
        protected Vector2Panel newObject() {
            Vector2Panel panel = new Vector2Panel();
            panel.addActionListener(PolygonFixtureDefPropertiesPanel.this);
            return panel;
        }
    };

    public void doBinder() {
        super.doBinder();
        PolygonFixtureDefModel object = PolygonFixtureDefModel.class.cast(this.object);
        if (pointPanels.size() == object.polygon.size()) {
            //when the vector points's size is equals of the polygon point size . we just update the bind infomation
            //so we can save a lot of space
            for (int i = 0; i < object.polygon.size(); i++) {
                Vector2Panel panel = pointPanels.get(i);
                Vector2 p = object.polygon.get(i);
                bind(p, "x", panel.spinnerX);
                bind(p, "y", panel.spinnerY);
            }
        } else {
            //Add , remove , Or bind new model should reach here
            for (Vector2Panel panel : pointPanels) {
                vector2PanelPool.free(panel);
            }
            pointPanels.clear();
            for (Vector2 p : object.polygon) {
                Vector2Panel panel = vector2PanelPool.obtain();
                this.pointPanels.add(panel);
                bind(p, "x", panel.spinnerX);
                bind(p, "y", panel.spinnerY);
            }
            createLayout();
        }
    }

    ;

    public JPanel getPolygonPanel() {
        return polygonPanel;
    }

    /**
     * Creates the layout for the panel.
     */
    private void createLayout() {
        // remove all the components
        this.polygonPanel.removeAll();

        // recreate the layout
        GroupLayout layout = (GroupLayout) this.polygonPanel.getLayout();


        int size = this.pointPanels.size();

        // create the horizontal layout
        ParallelGroup hGroup = layout.createParallelGroup();
        for (int i = 0; i < size; i++) {
            Vector2Panel panel = this.pointPanels.get(i);
            panel.lblNumber.setText("No." + (i + 1));
            hGroup.addComponent(panel);
            if (i < 3) {
                panel.btnRemove.setEnabled(false);
            } else {
                panel.btnRemove.setEnabled(true);
            }
        }
        // create the vertical layout
        SequentialGroup vGroup = layout.createSequentialGroup();
        for (int i = 0; i < size; i++) {
            Vector2Panel panel = this.pointPanels.get(i);
            vGroup.addComponent(panel);
        }
        layout.setHorizontalGroup(hGroup);
        layout.setVerticalGroup(vGroup);
    }

    public void actionPerformed(ActionEvent event) {
        PolygonFixtureDefModel model = PolygonFixtureDefModel.class.cast(this.object);
        // find the point panel issuing the event
        int index = this.pointPanels.indexOf(event.getSource());
        // check if its found
        if (index >= 0) {
            // check the type of event
            if ("add".equals(event.getActionCommand())) {
                // redo the layout
                if (model.polygon.size() > index + 1) {
                    Vector2 indexPlus = model.polygon.get(index + 1);
                    model.polygon.add(index + 1, new Vector2(model.polygon.get(index)).add(indexPlus.cpy().sub(model.polygon.get(index)).scl(.5f)));
                } else {
                    model.polygon.add(index + 1, new Vector2(model.polygon.get(index)).add(20, 20));
                }
                bind(model);
            } else if ("remove".equals(event.getActionCommand())) {
                // redo the layout
                model.polygon.remove(index);
                bind(model);
            }
        }
    }

    @Override
    public Binder getBinder(Object obj, String name, JComponent widget) {
        return new Binder(obj, name, widget) {
            @Override
            protected void postSolve() {
                if (null == object) return;
                Geometry.splitPolygon(PolygonFixtureDefModel.class.cast(object));
            }
        };
    }
}
